﻿Imports System
Imports System.CodeDom.Compiler
Imports System.Collections
Imports System.Collections.Generic
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.ComponentModel.Compiler
    Friend Class ValidationHelpers
        ' Methods
        Friend Shared Function IsActivitySourceInOrder(ByVal request As Activity, ByVal response As Activity) As Boolean
            If (request.Parent Is Nothing) Then
                Return True
            End If
            Dim list As New List([Of] Activity) { response }
            Dim activity As Activity = If(TypeOf response Is CompositeActivity, DirectCast(response, CompositeActivity), response.Parent)
            Do While (Not activity Is Nothing)
                list.Add(activity)
                activity = activity.Parent
            Loop
            Dim activity2 As Activity = request
            Dim item As CompositeActivity = If(TypeOf request Is CompositeActivity, DirectCast(request, CompositeActivity), request.Parent)
            Do While ((Not item Is Nothing) AndAlso Not list.Contains(item))
                activity2 = item
                item = item.Parent
            Loop
            If (item Is activity2) Then
                Return True
            End If
            Dim flag As Boolean = False
            Dim num As Integer = (list.IndexOf(item) - 1)
            num = If((num < 0), 0, num)
            Dim activity4 As Activity = list.Item(num)
            If (((item Is Nothing) OrElse Helpers.IsAlternateFlowActivity(activity2)) OrElse Helpers.IsAlternateFlowActivity(activity4)) Then
                flag = True
            Else
                Dim i As Integer
                For i = 0 To item.EnabledActivities.Count - 1
                    If (item.EnabledActivities.Item(i) Is activity2) Then
                        Exit For
                    End If
                    If (item.EnabledActivities.Item(i) Is activity4) Then
                        flag = True
                        Exit For
                    End If
                Next i
            End If
            Return Not flag
        End Function

        Friend Shared Function ValidateActivity(ByVal manager As ValidationManager, ByVal activity As Activity) As ValidationErrorCollection
            Dim errors As ValidationErrorCollection = ValidationHelpers.ValidateObject(manager, activity)
            Dim error As ValidationError
            For Each error In errors
                If Not [error].UserData.Contains(GetType(Activity)) Then
                    [error].UserData.Item(GetType(Activity)) = activity
                End If
            Next
            Return errors
        End Function

        Friend Shared Sub ValidateIdentifier(ByVal serviceProvider As IServiceProvider, ByVal identifier As String)
            If (serviceProvider Is Nothing) Then
                Throw New ArgumentNullException("serviceProvider")
            End If
            Dim supportedLanguage As SupportedLanguages = CompilerHelpers.GetSupportedLanguage(serviceProvider)
            Dim codeDomProvider As CodeDomProvider = CompilerHelpers.GetCodeDomProvider(supportedLanguage)
            If ((((supportedLanguage = SupportedLanguages.CSharp) AndAlso identifier.StartsWith("@", StringComparison.Ordinal)) OrElse (((supportedLanguage = SupportedLanguages.VB) AndAlso identifier.StartsWith("[", StringComparison.Ordinal)) AndAlso identifier.EndsWith("]", StringComparison.Ordinal))) OrElse Not codeDomProvider.IsValidIdentifier(identifier)) Then
                Throw New Exception(SR.GetString("Error_InvalidLanguageIdentifier", New Object() { identifier }))
            End If
        End Sub

        Friend Shared Function ValidateIdentifier(ByVal propName As String, ByVal context As IServiceProvider, ByVal identifier As String) As ValidationError
            If (context Is Nothing) Then
                Throw New ArgumentNullException("context")
            End If
            Dim error As ValidationError = Nothing
            If ((identifier Is Nothing) OrElse (identifier.Length = 0)) Then
                [error] = New ValidationError(SR.GetString("Error_PropertyNotSet", New Object() { propName }), &H116)
            Else
                Try 
                    ValidationHelpers.ValidateIdentifier(context, identifier)
                Catch exception As Exception
                    [error] = New ValidationError(SR.GetString("Error_InvalidIdentifier", New Object() { propName, exception.Message }), &H119)
                End Try
            End If
            If (Not [error] Is Nothing) Then
                [error].PropertyName = propName
            End If
            Return [error]
        End Function

        Friend Shared Function ValidateNameProperty(ByVal propName As String, ByVal context As IServiceProvider, ByVal identifier As String) As ValidationError
            If (context Is Nothing) Then
                Throw New ArgumentNullException("context")
            End If
            Dim error As ValidationError = Nothing
            If ((identifier Is Nothing) OrElse (identifier.Length = 0)) Then
                [error] = New ValidationError(SR.GetString("Error_PropertyNotSet", New Object() { propName }), &H116)
            Else
                Dim supportedLanguage As SupportedLanguages = CompilerHelpers.GetSupportedLanguage(context)
                Dim codeDomProvider As CodeDomProvider = CompilerHelpers.GetCodeDomProvider(supportedLanguage)
                If ((((supportedLanguage = SupportedLanguages.CSharp) AndAlso identifier.StartsWith("@", StringComparison.Ordinal)) OrElse (((supportedLanguage = SupportedLanguages.VB) AndAlso identifier.StartsWith("[", StringComparison.Ordinal)) AndAlso identifier.EndsWith("]", StringComparison.Ordinal))) OrElse Not codeDomProvider.IsValidIdentifier(codeDomProvider.CreateEscapedIdentifier(identifier))) Then
                    [error] = New ValidationError(SR.GetString("Error_InvalidIdentifier", New Object() { propName, SR.GetString("Error_InvalidLanguageIdentifier", New Object() { identifier }) }), &H119)
                End If
            End If
            If (Not [error] Is Nothing) Then
                [error].PropertyName = propName
            End If
            Return [error]
        End Function

        Friend Shared Function ValidateObject(ByVal manager As ValidationManager, ByVal obj As Object) As ValidationErrorCollection
            Dim errors As New ValidationErrorCollection
            If (Not obj Is Nothing) Then
                Dim type As Type = obj.GetType
                If (type.IsPrimitive OrElse (type Is GetType(String))) Then
                    Return errors
                End If
                Dim flag As Boolean = False
                Dim context As Dictionary([Of] Integer, Object) = [TryCast](manager.Context.Item(GetType(Dictionary([Of] Integer, Object))),Dictionary([Of] Integer, Object))
                If (context Is Nothing) Then
                    context = New Dictionary([Of] Integer, Object)
                    manager.Context.Push(context)
                    flag = True
                End If
                Try 
                    If context.ContainsKey(obj.GetHashCode) Then
                        Return errors
                    End If
                    context.Add(obj.GetHashCode, obj)
                    Try 
                        Dim validator As Validator
                        For Each validator In manager.GetValidators(type)
                            errors.AddRange(validator.Validate(manager, obj))
                        Next
                    Finally
                        context.Remove(obj.GetHashCode)
                    End Try
                Finally
                    If flag Then
                        manager.Context.Pop
                    End If
                End Try
            End If
            Return errors
        End Function

        Friend Shared Function ValidateProperty(ByVal manager As ValidationManager, ByVal activity As Activity, ByVal obj As Object, ByVal propertyValidationContext As PropertyValidationContext) As ValidationErrorCollection
            Return ValidationHelpers.ValidateProperty(manager, activity, obj, propertyValidationContext, Nothing)
        End Function

        Friend Shared Function ValidateProperty(ByVal manager As ValidationManager, ByVal activity As Activity, ByVal obj As Object, ByVal propertyValidationContext As PropertyValidationContext, ByVal extendedPropertyContext As Object) As ValidationErrorCollection
            If (manager Is Nothing) Then
                Throw New ArgumentNullException("manager")
            End If
            If (obj Is Nothing) Then
                Throw New ArgumentNullException("obj")
            End If
            If (propertyValidationContext Is Nothing) Then
                Throw New ArgumentNullException("propertyValidationContext")
            End If
            Dim errors As New ValidationErrorCollection
            manager.Context.Push(activity)
            manager.Context.Push(propertyValidationContext)
            If (Not extendedPropertyContext Is Nothing) Then
                manager.Context.Push(extendedPropertyContext)
            End If
            Try 
                errors.AddRange(ValidationHelpers.ValidateObject(manager, obj))
            Finally
                manager.Context.Pop
                manager.Context.Pop
                If (Not extendedPropertyContext Is Nothing) Then
                    manager.Context.Pop
                End If
            End Try
            Return errors
        End Function

        Friend Shared Function ValidateUniqueIdentifiers(ByVal rootActivity As Activity) As ValidationErrorCollection
            If (rootActivity Is Nothing) Then
                Throw New ArgumentNullException("rootActivity")
            End If
            Dim hashtable As New Hashtable
            Dim errors As New ValidationErrorCollection
            Dim queue As New Queue
            queue.Enqueue(rootActivity)
            Do While (queue.Count > 0)
                Dim activity As Activity = DirectCast(queue.Dequeue, Activity)
                If activity.Enabled Then
                    If hashtable.ContainsKey(activity.QualifiedName) Then
                        Dim item As New ValidationError(SR.GetString("Error_DuplicatedActivityID", New Object() { activity.QualifiedName }), &H602) { _
                            .PropertyName = "Name" _
                        }
                        item.UserData.Item(GetType(Activity)) = activity
                        errors.Add(item)
                    Else
                        hashtable.Add(activity.QualifiedName, activity)
                    End If
                    If (TypeOf activity Is CompositeActivity AndAlso ((activity.Parent Is Nothing) OrElse Not Helpers.IsCustomActivity([TryCast](activity,CompositeActivity)))) Then
                        Dim activity2 As Activity
                        For Each activity2 In Helpers.GetAllEnabledActivities(DirectCast(activity, CompositeActivity))
                            queue.Enqueue(activity2)
                        Next
                    End If
                End If
            Loop
            Return errors
        End Function

    End Class
End Namespace

